<?php


namespace app\api\controller\v27;


use app\aliyun\controller\AliyunFilterWord;
use app\api\controller\v2\Auth;
use app\chat\LiveMessage as CharLiveMessage;
use app\common\cachemodel\live\LiveAnchorInfo;
use app\common\cachemodel\live\LiveAwardAcitveRecord;
use app\common\cachemodel\live\LiveCoupon;
use app\common\cachemodel\live\LiveCouponActiveRecord;
use app\common\cachemodel\live\LiveCouponActiveGiveRecord;
use app\common\cachemodel\live\LiveDisableSendMsg;
use app\common\cachemodel\live\LiveGift;
use app\common\cachemodel\live\LiveGiftSendRecord;
use app\common\cachemodel\live\LiveMessage as LiveMessageModel;
use app\common\cachemodel\live\LiveMessageReport;
use app\common\cachemodel\live\LiveRecordingInfo;
use app\common\cachemodel\live\LiveRecordUserHot;
use app\common\cachemodel\live\LiveSignHotDay;
use app\common\cachemodel\live\LiveStatusDataRecord;
use app\common\cachemodel\live\LiveUserContribution;
use app\common\cachemodel\live\LiveUserGiftBag;
use app\common\cachemodel\live\LiveUserGiftBagRecord;
use app\common\cachemodel\OrdersLib;
use app\common\cachemodel\Recode;
use app\common\cachemodel\UserCoupon;
use app\common\cachemodel\ZhunleUserAccount;
use app\common\cachemodel\ZhunleUserAccountRecord;
use app\common\cachemodel\ZlUserVip;
use app\common\lib\exception\ApiException;
use app\common\lib\SensorsData;
use app\common\model\Goods;
use Exception;
use think\Db;
use think\Log;
use think\response\Json;

class UserLive extends Auth
{
    private $couponTypeName = [
        1 => '折扣',
        2 => '立减',
        3 => '满减',
        4 => '随机',
        5 => '免费',
    ];

    /**
     * 发送直播间弹幕
     * @return Json
     * @throws Exception
     */
    public function sendMessage()
    {
        $content = trim(input('content/s', ''));
        $liveId = input('live_id/d', 0);
        $liveRecordId = input('live_record_id/d', 0);
        (new LiveRecordingInfo())->checkRecordId($liveId, $liveRecordId);
        // 禁言判断
        if ((new LiveDisableSendMsg())->getUserIsDisableSendMsg($liveId, $liveRecordId, $this->user['id']))
        {
            return show(config('code.error'), '已被禁言，发送失败～');
        }

        if (empty($content))
        {
            return show(config('code.error'), '消息不能为空');
        }
        if (mb_strlen($content) > 50)
        {
            return show(config('code.error'), '消息最长50字');
        }

        $in_sign = 0;

        if ($this->user['rid'])
        {
            try
            {
                $recodeInfo = (new Recode())->getInfoById($this->user['rid'], ['sun']);
                $in_sign = (int)(explode('-', $recodeInfo['sun'])[0]);
            }
            catch (\Exception $e)
            {
            }
        }


        $content = htmlentities($content);

        $userVipInfo = (new ZlUserVip())->getInfoById($this->user['id']);

        $userVipLevel = $userVipInfo ? (int)$userVipInfo['vip_level'] : 0;
        $userRanking = (new LiveUserContribution())->getUserRanking($liveId, $this->user['id'], 50);

        $messageData = [
            'type' => 'pop_msg',
            'pop_msg' => [
                'user_info' => [
                    'uen' => $this->user['uen'],
                    'name' => $this->user['nickname'],
                    'avatar' => $this->user['avatar'],
                    'vip_level' => $userVipLevel,
                    'rank_index' => $userRanking, // 获取用户贡献榜排名
                ],
                'msg_info' => [
                    'id' => 0,
                    'color' => '#ffffff',
                    'content' => $content
                ]
            ]
        ];

        // 发送内容检测
        $res = AliyunFilterWord::checkText($content, 'article_comment');
        if ($res)
        {   // 弹幕违规 直接返回
            return show(424, '发送失败', $messageData);
        }

        $code = 200;
        $msg = '发送成功';
        $data = [];
        $anchInfo = (new LiveAnchorInfo())->getInfoById($liveId);
        try
        {
            $insertData = [
                'uid' => $this->user['id'],
                'type' => 1,
                'live_id' => $liveId,
                'content' => $content,
                'create_time' => $this->request->time(),
            ];
            //  弹幕数新增 弹幕入库
            $messageId = (new LiveMessageModel())->insertMessage($liveRecordId, $insertData, $in_sign);
            if ($messageId)
            {
                $messageData['pop_msg']['msg_info']['id'] = $messageId;

                CharLiveMessage::sendMsg(['type' => 'all', 'live_id' => $liveId, 'id' => $liveId, 'uid' => $this->user['id']], 'pop_msg', $messageData['pop_msg']);

                // 参加抽奖活动
                (new LiveAwardAcitveRecord())->awardActiveAdd($liveId, $liveRecordId, $this->user['id'], 1, $content);

                #神策打点 53 校准生辰下单 RectificationBuy
                $sensorsTrackData = [
                    'hoster_name' => $anchInfo['name'] ?? '',
                    'live_id' => $liveId,
                    'is_success' => true,
                    'failed_reson' => '',
                    'message_length' => mb_strlen($content),
                    'live_record_id' => $liveRecordId
                ];
            } else
            {
                $code = 424;
                $msg = '发送失败';
                $data = $messageData;
                $sensorsTrackData = [
                    'hoster_name' => $anchInfo['name'] ?? '',
                    'live_id' => $liveId,
                    'is_success' => false,
                    'failed_reson' => '服务异常,数据入库失败',
                    'message_length' => mb_strlen($content),
                    'live_record_id' => $liveRecordId
                ];
            }
        }
        catch (Exception $e)
        {
            $code = config('code.error');
            $msg = '服务异常；发送消息失败！';
            $data = [];
            $sensorsTrackData = [
                'hoster_name' => $anchInfo['name'] ?? '',
                'live_id' => $liveId,
                'is_success' => false,
                'failed_reson' => $e->getMessage(),
                'message_length' => mb_strlen($content),
                'live_record_id' => $liveRecordId
            ];
        }
        #神策打点 132 发送弹幕 LiveMessageSend
        SensorsData::track($this->user['id'], true, 'LiveMessageSend', $sensorsTrackData);
        if ($code === 200)
        {
            return show(config('code.success'), '发送成功', ['msg_id' => $messageId ?? 0, 'msg_color' => $messageData['pop_msg']['msg_info']['color']]);
        }
        return show($code, $msg, $data);
    }

    /**
     * 背包礼物变动记录
     * @return \think\response\Json
     * @throws \Exception
     */
    public function bagChangeList()
    {
        $bagRecord = (new LiveUserGiftBagRecord())->getUserGiftBagRecord($this->user['id']);
        return show(config('code.success'), '请求成功', $bagRecord);
    }

    /**
     * 赠送礼物
     * @throws ApiException
     */
    public function sendGifts()
    {
        $liveId = input('live_id/d', 0);
        $liveRecordId = input('live_record_id/d', 0);
        (new LiveRecordingInfo())->checkRecordId($liveId, $liveRecordId);
        $giftId = input('gift_id/d', 0);
        $num = input('num/d', 0);
        $type = input('type/d', 0);//1=>准币赠送 2=>背包赠送
        $password = input('password/s', '');//付费礼物需要密码
        $time = time();
        //判断当前直播间是否有直播
        $LiveRecordingInfoModel = new LiveRecordingInfo();
        $liveRecordInfo = $LiveRecordingInfoModel->getInfoById($liveRecordId);
        if (!$liveRecordInfo || (int)$liveRecordInfo['status'] !== 1)
        {
            return show(config('code.error'), '请求异常');
        }
        $gift = (new LiveGift())->getInfoById($giftId);
        if (!$gift)
        {
            return show(config('code.error'), '请求异常');
        }

        $inSign = 0;
        if ($this->user['rid'])
        {
            try
            {
                $recodeInfo = (new Recode())->getInfoById($this->user['rid'], ['sun']);
                $inSign = (int)(explode('-', $recodeInfo['sun'])[0]);
            }
            catch (\Exception $e)
            {
            }
        }
        $anchInfo = (new LiveAnchorInfo())->getInfoById($liveId);
        $goodsHot = $gift['hot'] * $num;
        $goodsCoin = $gift['coin'] * $num;
        $contributionValue = $gift['contribution'] * $num;
        //背包赠送
        if ($type === 2)
        {
            //背包验证
            $bagGift = (new LiveUserGiftBag())->getUserGiftBag($this->user['id']);
            $bagGift = array_column($bagGift, null, 'gid');
            if (empty($bagGift[$giftId]))
            {
                return show(config('code.error'), '您的背包没有当前礼物!');
            }
            if ($bagGift[$giftId]['num'] < $num)
            {
                return show(config('code.error'), '您的背包礼物数量不够!');
            }
            #神策打点 142 背包礼物礼物赠送成功 LiveBackpackGiftGivingSuccess
            SensorsData::track($this->user['id'], true, 'LiveBackpackGiftGivingSuccess', [
                'left_num' => $bagGift[$giftId]['num'] - $num,
                'live_id' => $liveId,
                'hoster_name' => $anchInfo['name'] ?? '',
                'live_record_id' => $liveRecordId
            ]);
            $type = 2;
            $changeId = (new LiveUserGiftBagRecord())->saveData($this->user['id'], ['uid' => $this->user['id'], 'gid' => $giftId, 'flag' => 1, 'live_record_id' => $liveRecordInfo['id'], 'live_id' => $liveId, 'change_num' => $num, 'create_time' => $time]);
            (new LiveUserGiftBag())->sendUserGift($this->user['id'], $giftId, $num * -1);
        }//准币赠送
        else
        {
            if ((int)$gift['type'] === 1)
            {
                $sensorsTrackData = [
                    'is_success' => false,
                    'coin_num' => $goodsCoin,
                    'live_id' => $liveId,
                    'failed_reson' => '请求异常',
                    'hoster_name' => $anchInfo['name'] ?? '',
                    'live_record_id' => $liveRecordId
                ];
                #神策打点 139 礼物赠送 LiveGiftGiving
                SensorsData::track($this->user['id'], true, 'LiveGiftGiving', $sensorsTrackData);
                return show(config('code.error'), '请求异常');
            }

            if ($password === '')
            {//422 弹出准币支付输入密码框前端alert展示准币价格，通过服务器返回的coin，进行展示  app端第一开始传给服务器是空的，后来保存在app本地
                $sensorsTrackData = [
                    'is_success' => false,
                    'coin_num' => $goodsCoin,
                    'live_id' => $liveId,
                    'failed_reson' => '未输入准币密码',
                    'hoster_name' => $anchInfo['name'] ?? '',
                    'live_record_id' => $liveRecordId
                ];
                #神策打点 139 礼物赠送 LiveGiftGiving
                SensorsData::track($this->user['id'], true, 'LiveGiftGiving', $sensorsTrackData);
                return show(422, '请输入准币密码！', ['coin' => $goodsCoin]);
            }

            $ZhunleUserAccountModel = new ZhunleUserAccount();
            //准币支付验证
            $userCoinInfo = $ZhunleUserAccountModel->getUserCoinFromCache($this->user['id']);
            $userCoin = $userCoinInfo ? (int)$userCoinInfo['balance'] : 0;
            //准币支付验证
            $ZhunleUserAccountModel->verifyCoinPay($userCoinInfo, $password, $goodsCoin, true);
            //准币消费明细变动
            $total_amount = OrdersLib::getOrderCoinTotalAmount($goodsCoin);
            $balance = $userCoin - $goodsCoin;
            $records = [
                'status' => 0,
                'account' => 0,
                'uid' => $this->user['id'],
                'consumer_type' => 3,
                'order_type' => 0,
                'gid' => 0,
                'pray_date' => 0,
                'rid' => 0,
                'total_amount' => $total_amount,
                'coin_num' => $goodsCoin,
                'balance' => $balance,
                'order_id' => '',
                'trade_type' => 4,
                'create_time' => time()
            ];
            //增加准币明细记录
            $records['id'] = (new ZhunleUserAccountRecord())->SaveData($this->user['id'], $records);
            $ZhunleUserAccountModel->updateCoinInfo($records['uid'], 2, $records, $goodsCoin, 0);
            $changeId = $records['id'];
            $type = 1;
        }
        (new LiveGiftSendRecord())->saveData($this->user['id'], $type, ['uid' => $this->user['id'], 'gid' => $giftId, 'live_record_id' => $liveRecordInfo['id'], 'live_id' => $liveId, 'type' => $type, 'send_num' => $num, 'oid' => $changeId, 'create_time' => $time]);

        //热度贡献值变动
        $LiveStatusDataRecordModel = new LiveStatusDataRecord();
        $LiveStatusDataRecordModel->setMinuteInc($liveId, 'gift_coin', $goodsCoin);
        $LiveStatusDataRecordModel->setMinuteInc($liveId, 'gift_hot_num', $goodsHot);
        // 用户热度数 自增
        (new LiveRecordUserHot())->userHotInc($this->user['id'], $liveId, $liveRecordId, 'gift_hot', $goodsHot);
        if ($inSign)
        {
            // 每日星座点赞 热度自增
            (new LiveSignHotDay())->setDaySignInc($liveId, $liveRecordId, $inSign, $goodsHot);
        }
        $resStatus = (new LiveUserContribution())->setLiveUserContributionValueInc($liveId, $liveRecordId, $this->user['id'], $contributionValue); // 用户贡献值增加 及 排行榜更新
        //向所有人发送消息
        $userRanking = (new LiveUserContribution())->getUserRanking($liveId, $this->user['id'], 50);
        $userVipInfo = (new ZlUserVip())->getInfoById($this->user['id']);
        $userVipLevel = $userVipInfo ? (int)$userVipInfo['vip_level'] : 0;
        CharLiveMessage::sendMsg(['type' => 'all', 'live_id' => $liveId, 'id' => $liveId], 'pop_gift', [
            'user_info' =>
                [
                    'uen' => $this->user['uen'],
                    'name' => $this->user['nickname'],
                    'avatar' => $this->user['avatar'],
                    'vip_level' => $userVipLevel,
                    'rank_index' => $userRanking, //  获取用户贡献榜排名
                ],
            'gift_info' =>
                [
                    'id' => $giftId,
                    'name' => $gift['name'],
                    'count' => $num,
                    'img' => $gift['img'],
                    'coin' => $goodsCoin ?? 0,
                    'lottie' => $gift['is_lottie'] > 0 ? json_decode($gift['lottie'], true) : null
                ],
        ]);

        if ($resStatus === 2) // 荣升榜一
        {
            CharLiveMessage::sendMsg(CharLiveMessage::who(CharLiveMessage::WHO_TYPE_ALL, $liveId, $liveId), CharLiveMessage::MSG_TYPE_POP_HEADER, [
                'title' => "恭喜 {$this->user['nickname']} 荣升榜一！",
                'target' => 'local',
                'link' => '',
                'continue_second' => 5,
            ]);
        }

        //神策打点
        if ($type === 1)
        {
            $sensorsTrackData = [
                'is_success' => true,
                'coin_num' => $goodsCoin,
                'live_id' => $liveId,
                'failed_reson' => '',
                'hoster_name' => $anchInfo['name'] ?? '',
                'live_record_id' => $liveRecordId
            ];
            #神策打点 139 礼物赠送 LiveGiftGiving
            SensorsData::track($this->user['id'], true, 'LiveGiftGiving', $sensorsTrackData);
        }
        return show(config('code.success'), '赠送成功', ['rank_index' => $userRanking]);
    }

    /**
     * 领取优惠券
     */
    public function giveCoupon()
    {
        $id = input('id/d', 0);
        $liveId = input('live_id/d', 0);
        $liveRecordId = input('live_record_id/d', 0);
        (new LiveRecordingInfo())->checkRecordId($liveId, $liveRecordId);
        $time = time();

        $activeInfo = (new LiveCouponActiveRecord())->getInfoById($id);

        if ($activeInfo['live_id'] != $liveId)
        {
            return show(config('code.error'), '抱歉已经抢完了');
        }

        $liveCouponInfo = (new LiveCoupon())->getInfoById($activeInfo['live_cid']);

        $anchInfo = (new LiveAnchorInfo())->getInfoById($liveId);

        $sensorsTrackData = [   // 神策打点数据
            'hoster_name' => $anchInfo['name'] ?? '',
            'live_id' => $liveId,
            'live_record_id' => $liveRecordId,
            'coupon_name' => $liveCouponInfo['lcname'],
            'is_geted' => false,
        ];

        // 判断是否领取过了
        $num = (new LiveCouponActiveGiveRecord())->where(['live_id' => $liveId, 'coupon_active' => $id, 'uid' => $this->user['id']])->count();
        if ($num)
        {
            SensorsData::track($this->user['id'], true, 'LiveCouponRob', $sensorsTrackData);
            return show(config('code.error'), '抱歉已经抢过了');
        }

        if ($time > ($activeInfo['create_time'] + $activeInfo['time'] * 60 + 10)) // 增加额外10秒 网络容错时间
        {
            SensorsData::track($this->user['id'], true, 'LiveCouponRob', $sensorsTrackData);
            return show(config('code.error'), '抱歉已经抢完了');
        }


        if ($activeInfo['user_group_type'] == 2)
        {
            $userVipLevel = (new ZlUserVip())->getUserVipLevel($this->user['id']);

            if ($userVipLevel < 1)
            {
                SensorsData::track($this->user['id'], true, 'LiveCouponRob', $sensorsTrackData);
                return show(config('code.error'), '抱歉已经抢完了');
            }
        }

        if ($activeInfo['send_num'] >= $activeInfo['total_num'])
        {
            SensorsData::track($this->user['id'], true, 'LiveCouponRob', $sensorsTrackData);
            return show(config('code.error'), '抱歉已经抢完了');
        }
        $liveCouponActiveModel = new LiveCouponActiveRecord();

        $sendNum = $liveCouponActiveModel->CouponSendNumInc($id, 1);

        if ($sendNum > $activeInfo['total_num'])
        {
            SensorsData::track($this->user['id'], true, 'LiveCouponRob', $sensorsTrackData);
            return show(config('code.error'), '抱歉已经抢完了');
        }

        try
        {
            $cData = [
                'uid' => $this->user['id'],
                'c_id' => $liveCouponInfo['cid'],
                'ur_id' => $liveCouponInfo['ur_id'],
                'start_time' => $time,
                'end_time' => strtotime("+{$activeInfo['coupon_expire_time']} hours", $time),
                'give_time' => $time,
                'status' => 0,
                'price' => 0,
                'is_give' => 0,
                'live_id' => $activeInfo['live_id'],
                'create_time' => $time,
                'update_time' => 0,
            ];
            $userCouponModel = new UserCoupon();

            // 写入用户卡券中心
            $userCouponModel->allowField(true)->save($cData);
            $ucId = $userCouponModel->id;
            // 更新用户卡券中心缓存
            $userCouponModel->listDataAdd($this->user['id'], [$ucId => $ucId], 1);
            // 写入抢券记录
            $giveRecord = [
                'live_id' => $liveId,
                'live_record_id' => $liveRecordId,
                'coupon_active' => $id,
                'uid' => $this->user['id'],
                'cid' => $liveCouponInfo['cid'],
                'user_cid' => $ucId,
                'create_time' => $time,
            ];
            (new LiveCouponActiveGiveRecord())->insert($giveRecord);
            // 活动赠送优惠券增加
            (new LiveCouponActiveRecord())->where('id', $id)->setInc('send_num', 1);
            // 神策打点
            $gidsArr = explode(',', $liveCouponInfo['gids']);
            $liveCouponInfo['couponRangeArr'] = (new Goods())->where('id', 'in', $gidsArr)->column('name');
            // 神策打点 75 获得优惠券 AcquireCoupon
            SensorsData::track($this->user['id'], true, 'AcquireCoupon', [
                'refer_name' => '',
                'refer_link' => '',
                'coupon_name' => $liveCouponInfo['desc'],
                'coupon_expire' => date('Y-m-d H:i:s', $cData['end_time']),
                'coupon_type' => $this->couponTypeName[$liveCouponInfo['type']],
                'coupon_range' => $liveCouponInfo['couponRangeArr'],
                'acquire_channel' => "直播间【{$liveId}】抢优惠券活动ID【{$id}】",
                'is_give' => false,
                'acquire_scene' => '直播间抢优惠券',
            ]);

            $ctype = (int)($liveCouponInfo['use_range'] ?? 0);
            // 直播抢券 打点
            $sensorsTrackData['is_geted'] = true;   // 是否抢到
            SensorsData::track($this->user['id'], true, 'LiveCouponRob', $sensorsTrackData);

            $resData = [
                'cname' => $liveCouponInfo['desc'],
                'target' => isset(LiveCoupon::$goodsTypeTLinkConfig[$ctype]) ? LiveCoupon::$goodsTypeTLinkConfig[$ctype]['target'] : 'local',
                'link' => isset(LiveCoupon::$goodsTypeTLinkConfig[$ctype]) ? LiveCoupon::$goodsTypeTLinkConfig[$ctype]['link'] : 'empty'
            ];

            (new \app\common\cachemodel\Goods())->goodsTargetLink($ctype, $resData['link']);

            return show(config('code.success'), '领取优惠券成功', $resData);
        }
        catch (\Exception $e)
        {
            SensorsData::track($this->user['id'], true, 'LiveCouponRob', $sensorsTrackData);
            Log::write("直播间【{$liveId}】抢优惠券失败;id:{$id};uid:{$this->user['id']};error:{$e->getMessage()};file:{$e->getFile()};line:{$e->getLine()}", 'error', true);
            return show(config('code.error'), '服务异常；请稍后再试～');
        }
    }

    /**
     * 弹幕举报
     */
    public function messageReport()
    {
        $id = input('id/d', 0);
        $liveId = input('live_id/d', 0);
        $liveRecordId = input('live_record_id/d', 0);
        (new LiveRecordingInfo())->checkRecordId($liveId, $liveRecordId);
        $reason = input('reason/s', '');

        if (empty($id) || empty($liveId) || empty($reason))
        {
            return show(config('code.error'), '请求异常，请稍后再试～');
        }

        try
        {
            $num = (new LiveMessageReport())->where([
                'message_id' => $id,
                'live_record_id' => $liveRecordId,
                'uid1' => $this->user['id'],
            ])->count();

            if ($num)
            {   // 已经举报过了
                return show(config('code.success'), '举报成功');
            }

            // 获取弹幕信息
            $messageInfo = Db::table('`live_data`.live_message_' . $liveRecordId)->where('id', $id)->field('uid,content')->find();
            // 举报数据
            $reportData = [
                'message_id' => $id,
                'live_id' => $liveId,
                'live_record_id' => $liveRecordId,
                'reason' => $reason,
                'uid1' => $this->user['id'],
                'uid2' => $messageInfo['uid'],
                'status' => 0,
                'content' => $messageInfo['content'],
                'create_time' => $this->request->time(),
            ];

            (new LiveMessageReport())->insert($reportData);

            $anchInfo = (new LiveAnchorInfo())->getInfoById($liveId);
            $sensorsTrackData = [
                'complain_reason' => $reason,
                'live_id' => $liveId,
                'hoster_name' => $anchInfo['name'] ?? '',
                'live_record_id' => $liveRecordId
            ];
            #神策打点 134 举报成功 LiveMessageComplainSuccess
            SensorsData::track($this->user['id'], true, 'LiveMessageComplainSuccess', $sensorsTrackData);

            return show(config('code.success'), '举报成功');
        }
        catch (\Exception $e)
        {
            Log::write("直播间【{$liveId}】弹幕举报失败;message_id:{$id};uid:{$this->user['id']};error:{$e->getMessage()};file:{$e->getFile()};line:{$e->getLine()}", 'error', true);
            return show(config('code.error'), '服务异常，请稍后再试～');
        }
    }

}
